<?php
abstract class BaseEntity{	
	
	public $attributes;	
	protected $repository;	
	public $logicDelete = false;
	public $saveWall = false;
	
	function __construct($id = 0) {
		$this->repository = Repository::getInstance();
		if($id > 0){
			$this->get($id);
		}else{		
        	$this->attributes = new Attributes();
		}        
    }       
	
	public function getAll($orderBy = '',$limit = 0,  $offset = 0, $count = false) {
		if($count){
			$sql = "Select count(*) as count from " . get_class($this) . " where " . $this->getIsDeletedFilterQuery();			
			return $this->repository->getValue($sql, "count");			
		}else{
			
			$limOff = $this->repository->getLimitOffset($limit, $offset);
			$orderBy = $this->repository->getOrderBy($orderBy);			
			$sql = "Select * from " . get_class($this) . " where " . $this->getIsDeletedFilterQuery() . $orderBy . $limOff;			
			return $this->repository->fetchAllObject($sql, get_class($this));			
		}
	}
	
	public function get($id) {
		$sql = "Select * from " . get_class($this) . " where id = " . $id;
		$this->attributes = $this->repository->fetchObject($sql, "Attributes");
	}
	
	public function delete($id = 0){
		if (!$id && isset($this->attributes) && $this->attributes && $this->attributes->id > 0){
			$id = $this->attributes->id;
			$this->attributes = new Attributes();
		}
		
		$class = get_class($this);
		$entity = new $class($id);
		$this->attributes = $entity->attributes;
		
		if($this->canEdit()){
		
			if($id){
				if($this->saveWall){
					$wall = new Wall();
					$wall->getByContainer($id,get_class($this));
					$wall->delete();
				}
				
				if(!$this->logicDelete){
					$sql = "Delete from " . get_class($this) . " where id = " . $id;
					$this->repository->query($sql);
					$this->attributes->id = $id;
					$this->deleteIcons();
					
					return true;
				}else{
					$sql = "UPDATE " . get_class($this) . " SET isDeleted = 1 where id = " . $id;
					$this->repository->query($sql);
					return true;
				}
			}
		}else{
			logError(langEcho("permission:delete:denied"));			
		}	
		
		return false;
	}	
	
	public function save($icon = true, $checkPermission = true, $raiseEvents = true, $validateRequired = "validateRequired"){
		
		if ( $validateRequired != "" && method_exists($this, $validateRequired) ){
			if (!$this->$validateRequired()){
				return false;	
			}
		}
		
		if ($this->attributes->id > 0){
			if(!$checkPermission || $this->canEdit()){
				$sql = "Update " . get_class($this) . " SET ";
				
				$first = true;
				foreach($this->attributes->data as $key => $value){
					if ($key != "id"){
						if($first){
							$sql .= $key . " = " . "'" . $value . "'";
							$first = false;
						}else{
							$sql .= ", " . $key . " = " . "'" . $value . "'";
						}
					}
				}
				$sql .= " where id = " . $this->attributes->id;
				
				$this->repository->query($sql);
				
				if($this->saveWall){
					$wall = new Wall();
					$wall->getByContainer($this->attributes->id,get_class($this));
					if(!$wall->attributes){
						$wall->attributes = new Attributes();
						$wall->attributes->containerId = $this->attributes->id;
						$wall->attributes->containerType = get_class($this);
					}
					$wall->attributes->date = time();
					$wall->save(false);
				}
				
				if ($raiseEvents && method_exists($this, "OnUpdated") ){
					$this->OnUpdated();					
				}
			}else{
				logError(langEcho("permission:delete:denied"));
				return false;
			}
		}else{
			$sql = "Insert into " . get_class($this) . " (";			
			
			foreach($this->attributes->data as $key => $value){
				if ($key != "id"){
					$keys[] = $key;
					$values[] = $value;
				}
			}
			
			$first = true;
			foreach ($keys as $key){
				if($first){
					$sql .= $key;
					$first = false; 	
				}else{
					$sql .= "," . $key;
				}
			}
			
			$sql .= ") values (";
			
			$first = true;
			foreach ($values as $value){
				if($first){
					$sql .= "'" . $this->repository->escape($value) . "'";
					$first = false; 	
				}else{
					$sql .= ",'" . $this->repository->escape($value) . "'";
				}
			}
			
			$sql.= ")";
						
			$this->repository->query($sql);
			$this->attributes->id = $this->repository->getLastId();
			
			if($this->saveWall){
				$wall = new Wall();
				$wall->attributes->containerId = $this->attributes->id;
				$wall->attributes->containerType = get_class($this);
				$wall->attributes->date = time();
				$wall->save(false);
			}
			
			if ($raiseEvents && method_exists($this, "OnInserted") ){
				$this->OnInserted();					
			}
		}
		
		if($icon){
			return $this->saveIcon();
		}
		
		return true;
	}
	
	function getRelatedObject($id, $className){	
		return new $className($id);		 
	}
	
	function getRelatedObjects($keyValues, $className,$orderBy = '', $limit = 0, $offset = 0, $count = false){		
		foreach($keyValues as $key => $value){
			if(!isset($where)){
				$where = " where " . $key . " = '" . $value . "' ";
			}else{
				$where .= " and " . $key . " = '" . $value . "' ";
			}
		}
		
		if($count){
			$sql = "Select count(*) as count from " . $className . $where;
			return $this->repository->getValue($sql, "count");
		}else{			 
			$limOff = $this->repository->getLimitOffset($limit, $offset);
			$orderBy = $this->repository->getOrderBy($orderBy);			

			if(isset($where)){
				$where .= " and " . $this->getIsDeletedFilterQuery();
			}else{
				$where = $this->getIsDeletedFilterQuery();
			}
			
			$sql = "Select * from " . $className . $where . $orderBy . $limOff;
			return $this->repository->fetchAllObject($sql, $className);
		}
				
	}

	function getRelatedObjectsJoined($keyValues, $className, $joinedTable="", $joinedTableFilterLogicDelete=false ,$orderBy = '', $limit = 0, $offset = 0, $count = false, $repeatedValues = array()){
		$join = "";
		
		if ($joinedTable != ""){
			$join = " JOIN $joinedTable as j on j.id = $className.id$joinedTable";
						
			if ($joinedTableFilterLogicDelete){
				$join .= " AND j.isDeleted = 0 ";
			}
		}
		
		$columnNames = $this->getColumnNames($joinedTable);
		$selectColumnsJoin = "";
		
		foreach($columnNames as $columnName){
			if ($columnName != "id"){
				
				if (in_array($columnName, $repeatedValues)){
					$selectColumnsJoin .= ",j." . $columnName . " as $columnName" . "Joined ";
				}
				else{
					$selectColumnsJoin .= ",j." . $columnName;
				}
			}
		}
		
		
		foreach($keyValues as $key => $value){
			if(!isset($where)){
				$where = " where " . $key . " = '" . $value . "' ";
			}else{
				$where .= " and " . $key . " = '" . $value . "' ";
			}
		}

		if($count){			
			$sql = "Select count(*) as count from " . $className . $join . $where;
			return $this->repository->getValue($sql, "count");
		}else{			 
			$limOff = $this->repository->getLimitOffset($limit, $offset);
			$orderBy = $this->repository->getOrderBy($orderBy);			
			$sql = "Select $className.* $selectColumnsJoin from " . $className . $join . $where . $orderBy . $limOff;
			

			return $this->repository->fetchAllObject($sql, $className);
		}
				
	}

	function getObjectsRelatedAdminUserJoined($keyValues, $className, $orderBy = '', $limit = 0, $offset = 0, $count = false){

		$join = " JOIN EntityAdministrator ea on ea.containerId = $className.id JOIN User as u on u.id = ea.idUser ";

		$columnNames = $this->getColumnNames("User");
		$selectColumnsJoin = "";
		
		foreach($columnNames as $columnName){
			if ($columnName != "id"){
				$selectColumnsJoin .= ",u." . $columnName;
			}
		}
		
		foreach($keyValues as $key => $value){
			if(!isset($where)){
				$where = " where " . $key . " = '" . $value . "' ";
			}else{
				$where .= " and " . $key . " = '" . $value . "' ";
			}
		}
				
		if($this->logicDelete){
			if (isset($where)){			
				$where .= " and $className.isDeleted = 0";
			}
			else{
				$where = " where $className.isDeleted = 0";
			}
		}
		
		if($count){
			$sql = "Select count(*) as count from " . $className . $where;
			return $this->repository->getValue($sql, "count");
		}else{			 
			$limOff = $this->repository->getLimitOffset($limit, $offset);
			$orderBy = $this->repository->getOrderBy($orderBy);			
			$sql = "Select $className.* $selectColumnsJoin from " . $className . $join . $where . $orderBy . $limOff;

			return $this->repository->fetchAllObject($sql, $className);
		}				
	}
	
	
	function search($where,$orderBy='', $limit = 0, $offset = 0, $count = false){
		if(isset($where)){
			$where .= " and " . $this->getIsDeletedFilterQuery();
		}else{
			$where = $this->getIsDeletedFilterQuery();
		}
		if($count){			
			$sql = "Select count(*) as count from " . get_class($this) . " where " . $where;			
			return $this->repository->getValue($sql, "count");
		}else{
			$limitOff = $this->repository->getLimitOffset($limit, $offset);
			$orderBy = $this->repository->getOrderBy($orderBy);			
			$sql = "Select * from " . get_class($this) . " where " . $where . $orderBy . $limitOff;

			return $this->repository->fetchAllObject($sql, get_class($this));
		}
	}
	
	function getByPattern($where){
		if(isset($where)){
			$where .= " and " . $this->getIsDeletedFilterQuery();
		}else{
			$where = $this->getIsDeletedFilterQuery();
		}
		$sql = "Select * from " . get_class($this) . " where " . $where;
		
		$this->attributes = $this->repository->fetchObject($sql, "Attributes");		
	}
	
	function insertFieldsFromRequest($validateRequired = "validateRequired"){		
		if(!$this->attributes->id > 0){
			$sql = "DESCRIBE " . get_class($this);
			$resource = $this->repository->query($sql);
			while($row = $this->repository->fetch($resource)){
				$this->attributes->$row["Field"] = ""; 
			}
		}
		foreach($this->attributes->data as $key => $value){
			if ($key != "id" && isset($_REQUEST[$key])){
				$this->attributes->$key = $_REQUEST[$key];
			}
		}				
				
		return $this->save(true,true,true,$validateRequired);		
	}

	
	
	function getIconPath($size = "list"){		
		return UPLOADPATH . get_class($this) . "/" . $this->attributes->id . "/icon".$size.".png"; 
	}
	
	function getDefaultIconPath($size = "list"){
		return PATHROOT . "images/" . get_class($this) . "/icon".$size.".png"; 
	}
	
	function hasIcon($size = "list"){
		return file_exists($this->getIconPath($size)); 
	}
	
	function hasDefaultIcon($size = "list"){
		return file_exists($this->getDefaultIconPath($size)); 
	}
		
	function getIcon($size = 'list'){
		if ($this->hasIcon($size)){
			$icon = "";
			if ($this->attributes->icon){
				$icon = "?" . $this->attributes->icon;
			}
			return UPLOADWWW . get_class($this) . "/" . $this->attributes->id . "/icon".$size.".png" . $icon;	
		}else{
			return WWWROOT .  "images/" . get_class($this) . "/icon".$size.".png";
		}
		
	}
	
	function getColumnNames($className){
		$sql = "DESCRIBE " . $className;
		$resource = $this->repository->query($sql);
		
		$columnNames = array();
		
		while($row = $this->repository->fetch($resource)){
			$columnNames[] = $row["Field"];
		}
		
		return $columnNames;
	}
	
	function deleteIcons(){		
		if(file_exists(UPLOADPATH . get_class($this) . "/" . $this->attributes->id)){			
			rrmdir(UPLOADPATH . get_class($this) . "/" . $this->attributes->id);	
		}
	}
	
	function saveIcon(){
		if (isset($_FILES['icon']) && $_FILES['icon']['error'] == 0){
			if (!file_exists(UPLOADPATH . get_class($this))){
				mkdir(UPLOADPATH . get_class($this));
			} 
			if(!file_exists(UPLOADPATH . get_class($this). "/" . $this->attributes->id)){
				mkdir(UPLOADPATH . get_class($this). "/" . $this->attributes->id);
			}
			if(validateImageFile($_FILES['icon']["tmp_name"])){
				file_put_contents($this->getIconPath("original"), file_get_contents($_FILES["icon"]["tmp_name"]));
				file_put_contents($this->getIconPath("list"), get_resized_image_from_existing_file($this->getIconPath("original"),70,70, false));							
				$this->updateIconVersion();
			}else{				
				logError(langEcho("not:an:image"));
				$this->delete();
				return false;
			}
		}
		return true;
	}
	
	function updateIconVersion(){		
		$sql = "UPDATE " . get_class($this) . " set icon = " . time() . " where id=" . $this->attributes->id;
		$this->repository->query($sql);	
	}
	
	function canEdit(){				
		if(isAdminLoggedIn()){
			return true;
		}

		return false;
	}
	
	protected function canEditEntity($containerId, $containerType, $userId, $className){
		$result = $this->getRelatedObjects(array("containerId" => $containerId, "containerType" => $containerType, "idUser" => $userId),$className,"",0,0,true);
		
		if($result>0)
			return true;
		else
			return false;
	}
	
	function getLastId(){
		$sql = "SELECT max(id) as max from " . get_class($this);
		return $this->repository->getValue($sql, "max");
	}
	
	protected function getIsDeletedFilterQuery(){
		if($this->logicDelete){
			return " isDeleted = 0 ";
		}
		
		return " 1=1 ";
	}
	
	function deleteEntityAdministratoByContainerIdAndType($containerId, $containerType){
		$sql = "Delete from " . get_class($this) . " where containerId = " . $containerId . " AND containerType = '" . $containerType . "'";
		$this->repository->query($sql);		
	}
}

?>